home *** CD-ROM | disk | FTP | other *** search
- /*
-
- Copyright (C) 1996 John W. Eaton
-
- This file is part of Octave.
-
- Octave is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- Octave is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- You should have received a copy of the GNU General Public License
- along with Octave; see the file COPYING. If not, write to the Free
- Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- */
-
- #if defined (__GNUG__)
- #pragma implementation
- #endif
-
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
-
- #include <cmath>
-
- #include <string>
-
- #include "dbleGEPBAL.h"
- #include "f77-fcn.h"
-
- extern "C"
- {
- int F77_FCN (dgebak, DGEBAK) (const char*, const char*, const int&,
- const int&, const int&, double*,
- const int&, double*, const int&, int&,
- long, long);
-
- int F77_FCN (reduce, REDUCE) (const int&, const int&, double*,
- const int&, double*, int&, int&,
- double*, double*);
-
- int F77_FCN (scaleg, SCALEG) (const int&, const int&, double*,
- const int&, double*, const int&,
- const int&, double*, double*,
- double*);
-
- int F77_FCN (gradeq, GRADEQ) (const int&, const int&, double*,
- const int&, double*, int&, int&,
- double*, double*);
- }
-
- int
- GEPBALANCE::init (const Matrix& a, const Matrix& b, const string& balance_job)
- {
- int a_nr = a.rows ();
- int a_nc = a.cols ();
- int b_nr = b.rows ();
-
- if (a_nr != a_nc || a_nr != b_nr || b_nr != b.cols ())
- {
- (*current_liboctave_error_handler)
- ("GEPBALANCE requires square matrices of the same size");
- return -1;
- }
-
- int n = a_nc;
-
- int info;
- int ilo;
- int ihi;
-
- Array<double> cscale (n);
- double *pcscale = cscale.fortran_vec ();
-
- Matrix wk (n, 6, 0.0);
- double *pwk = wk.fortran_vec ();
-
- // Back out the permutations:
- //
- // cscale contains the exponents of the column scaling factors in its
- // ilo through ihi locations and the reducing column permutations in
- // its first ilo-1 and its ihi+1 through n locations.
- //
- // cperm contains the column permutations applied in grading the a and b
- // submatrices in its ilo through ihi locations.
- //
- // wk contains the exponents of the row scaling factors in its ilo
- // through ihi locations, the reducing row permutations in its first
- // ilo-1 and its ihi+1 through n locations, and the row permutations
- // applied in grading the a and b submatrices in its n+ilo through
- // n+ihi locations.
-
- // Copy matrices into local structure.
-
- balanced_a_mat = a;
- balanced_b_mat = b;
-
- double *p_balanced_a_mat = balanced_a_mat.fortran_vec ();
- double *p_balanced_b_mat = balanced_b_mat.fortran_vec ();
-
- // Check for permutation option.
-
- char job = balance_job[0];
-
- if (job == 'P' || job == 'B')
- {
- F77_XFCN (reduce, REDUCE, (n, n, p_balanced_a_mat, n,
- p_balanced_b_mat, ilo, ihi,
- pcscale, pwk));
- }
- else
- {
- // Set up for scaling later.
-
- ilo = 1;
- ihi = n;
- }
-
- if (f77_exception_encountered)
- (*current_liboctave_error_handler) ("unrecoverable error in reduce");
- else
- {
- Array<double> cperm (n);
- double *pcperm = cperm.fortran_vec ();
-
- // Check for scaling option.
-
- if ((job == 'S' || job == 'B') && ilo != ihi)
- {
- F77_XFCN (scaleg, SCALEG, (n, n, p_balanced_a_mat, n,
- p_balanced_b_mat, ilo, ihi,
- pcscale, pcperm, pwk));
- }
- else
- {
- // Set scaling data to 0's.
-
- for (int i = ilo-1; i < ihi; i++)
- {
- cscale.elem (i) = 0.0;
- wk.elem (i, 0) = 0.0;
- }
- }
-
- if (f77_exception_encountered)
- (*current_liboctave_error_handler) ("unrecoverable error in scaleg");
- else
- {
- // Scaleg returns exponents, not values, so...
-
- for (int i = ilo-1; i < ihi; i++)
- {
- cscale.elem (i) = pow (2.0, cscale.elem (i));
- wk.elem (i, 0) = pow (2.0, -wk.elem (i, 0));
- }
-
- // Initialize balancing matrices to identity.
-
- left_balancing_mat = Matrix (n, n, 0.0);
- for (int i = 0; i < n; i++)
- left_balancing_mat (i, i) = 1.0;
-
- right_balancing_mat = left_balancing_mat;
-
- double *p_right_balancing_mat = right_balancing_mat.fortran_vec ();
- double *p_left_balancing_mat = left_balancing_mat.fortran_vec ();
-
- // Column permutations/scaling.
-
- char side = 'R';
-
- F77_XFCN (dgebak, DGEBAK, (&job, &side, n, ilo, ihi, pcscale,
- n, p_right_balancing_mat, n, info,
- 1L, 1L));
-
- if (f77_exception_encountered)
- (*current_liboctave_error_handler)
- ("unrecoverable error in dgebak");
- else
- {
- // Row permutations/scaling.
-
- side = 'L';
-
- F77_XFCN (dgebak, DGEBAK, (&job, &side, n, ilo, ihi, pwk,
- n, p_left_balancing_mat, n,
- info, 1L, 1L));
-
- #if 0
- // XXX FIXME XXX --- these four lines need to be added and
- // debugged. GEPBALANCE::init will work without them, though, so
- // here they are.
-
- if ((job == 'P' || job == 'B') && ilo != ihi)
- {
- F77_XFCN (gradeq, GRADEQ, (n, n, p_balanced_a_mat, n,
- p_balanced_b_mat, ilo, ihi,
- pcperm, pwk));
- }
- #endif
-
- if (f77_exception_encountered)
- (*current_liboctave_error_handler)
- ("unrecoverable error in dgebak");
- else
- {
- // Transpose for aa = cc*a*dd convention...
-
- left_balancing_mat = left_balancing_mat.transpose ();
- }
- }
- }
- }
-
- return info;
- }
-
- /*
- ;;; Local Variables: ***
- ;;; mode: C++ ***
- ;;; End: ***
- */
-